<?php
require_once dirname(__FILE__) . '/libraries/ServiceBase.php';
/**
 * SDO OAS库 读写 对外接口调用封装
 * 
 * @category SDO
 * @package OPEN
 * @author <xucongbin@snda.com> 2010-4-12 17:48 
 * @copyright SDO OP
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @link http://www.sdo.com/
 * @since File available since Release 1.0.0
 */
class OASApi extends ServiceBase
{
    /**
     * 授权信息，写死，格式：1.1.1,1.1.2,1.1.7,1.1.8,3.1.1
     */
    CONST AUTH_INFO_DEFAULT = '1.1.1';
    /**
     * IP端口，默认不填
     */
    CONST CLIENT_PORT_DEFAULT = "-1";
    /**
     * SOAP VERSION
     */
    CONST SOAP_VERSION = "SOAP_1_1";
    /**
     * 组状态默认值 1有效，2无效
     */
    CONST GROUP_STATUS_DEFAULT = 1;
    /**
     * 正式WSDL接口地址
     */
    CONST OAS_WSDL = "OASAPI_WSDL";
    /**
     * 联调WSDL接口地址
     */
    CONST PRE_OAS_WSDL = "PRE_OASAPI_WSDL";
    /**
     * 产品公钥默认值
     */
    CONST APP_PUBLIC_KEY_DEFAULT = "N/A";
    /**
     * 原来的编码格式
     */
    CONST IN_CHARSET = "UTF-8";
    /**
     * 转码后的编码格式
     */
    CONST OUT_CHARSET = "GBK";
    /**
     * 发送请求字段
     * @var string
     */
    CONST REQUEST_FIELD = 'req';
    /**
     * 操作列表,查询操作，仅在获取公钥时使用
     */
    protected static $OPTypeList = array(
        "add" => 1, 
        "update" => 2, 
        "delete" => 3, 
        "select" => 4
    );
    /**
     * 
     */
    protected static $errCodeMsg = array(
        - 10236001 => '参数校验错误', 
        - 10236002 => '操作（OPERATE)错误', 
        - 10236003 => '操作失败', 
        - 10236004 => ' ADD ID EXIST', 
        - 10236005 => ' MODIFY ID NOT EXIST', 
        - 10236006 => ' DELETE ID NOT EXIST', 
        - 10236007 => ' ADD SP NOT EXIST ', 
        - 10236008 => ' ADD ID EXIST ', 
        - 10236009 => ' MODIFY SP NOT EXIST', 
        - 10236010 => ' MODIFY ID NOT EXIST', 
        - 10236011 => ' DELETE SP NOT EXIST', 
        - 10236012 => ' DELETE ID NOT EXIST', 
        - 10236013 => ' ADD APP NOT EXIST ', 
        - 10236014 => ' ADD ID EXIST ', 
        - 10236015 => ' MODIFY APP NOT EXIST ', 
        - 10236016 => ' MODIFY ID NOT EXIST ', 
        - 10236017 => ' DELETE APP NOT EXIST ', 
        - 10236018 => ' DELETE ID NOT EXIST ', 
        - 10236019 => ' ADD APP NOT EXIST ', 
        - 10236020 => ' ADD AREA NOT EXIST ', 
        - 10236021 => ' ADD ID EXIST ', 
        - 10236022 => ' MODIFY APP NOT EXIST ', 
        - 10236023 => ' MODIFY AREA NOT EXIST ', 
        - 10236024 => ' MODIFY ID NOT EXIST ', 
        - 10236025 => ' DELETE APP NOT EXIST ', 
        - 10236026 => ' DELETE AREA NOT EXIST ', 
        - 10236027 => ' DELETE ID NOT EXIST ', 
        - 10236028 => ' ADD GROUP NOT EXIST ', 
        - 10236029 => ' ADD IP ALIAS EXIST ', 
        - 10236030 => ' MODIFY GROUP NOT EXIST ', 
        - 10236031 => ' MODIFY IP ALIAS NOT EXIST ', 
        - 10236032 => ' MODIFY GROUP LIST NOT EXIST ', 
        - 10236033 => ' DELETE GROUP NOT EXIST ', 
        - 10236034 => ' DELETE IP ALIAS NOT EXIST ', 
        - 10236035 => ' DELETE GROUP LIST NOT EXIST ', 
        - 10236036 => ' ADD SP NOT EXIST ', 
        - 10236037 => ' ADD SERVICE NOT EXIST ', 
        - 10236038 => ' ADD EXIST ', 
        - 10236039 => ' MODIFY SP NOT EXIST ', 
        - 10236040 => ' MODIFY SERVICE NOT EXIST ', 
        - 10236041 => ' MODIFY NOT EXIST ', 
        - 10236042 => ' DELETE SP NOT EXIST ', 
        - 10236043 => ' DELETE SERVICE NOT EXIST ', 
        - 10236044 => ' DELETE NOT EXIST ', 
        - 10236045 => ' QUERY SP NOT EXIST ', 
        - 10236046 => ' QUERY SERVICE NOT EXIST ', 
        - 10236047 => ' QUERY NOT EXIST ', 
        - 10236048 => ' ip alias不存在  ', 
        - 10236051 => 'MODIFY SP APP NOT MATCH', 
        - 10236052 => 'DELETE SP APP NOT MATCH', 
        - 10236053 => 'ADD SP APP NOT MATCH', 
        - 10236054 => 'MODIFY SP APP NOT MATCH', 
        - 10236055 => 'DELETE SP APP NOT MATCH', 
        - 10236056 => 'QUERY SP APP NOT MATCH'
    );
    /**
     * 产品操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数array(appId=>游戏id 和主键相同,
     * typeId=>游戏扣帐类型，默认0 该应用消费扣用户该应用相应帐户 1 该应用消费扣用户总帐,
     * appName=>游戏名称,
     * spId=>表示该服务应用的sp提供商,
     * timeTypeId=>表示消费模式 时长消费为1 pt点消费为2，OA转账为4，OA道具计费为5
     * createUser=>申请用户,
     * payTypeId=>货币类型,
     * manageId=>产品现状ID,
     * signArith=>1：MD5，2:RSA，默认为1,)
     * @param string $opType 操作
     * @param string $env  环境
     *
     * @return boolean 
     */
    public static function app (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType]) || ! isset($params['appId']) || ! isset($params['spId'])) {
            $message = "Invalid Parameter";
            return false;
        }
        if ($opType != "delete") {
            $need = array(
                'typeId', 
                'appName', 
                'timeTypeId', 
                'createUser', 
                'payTypeId', 
                'manageId', 
                'signArith'
            );
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
            $params['status'] = 1;
        } else {
            $need = array(
                'typeId', 
                'timeTypeId', 
                'payTypeId', 
                'manageId', 
                'signArith'
            );
            self::setDefault($params, $need);
        }
        $params['operate'] = self::$OPTypeList[$opType];
        $result = self::soapRequest('operateApp', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        if ($opType == "add") {
            $param = array(
                'appId' => $params['appId'], 
                'spId' => $params['spId'], 
                'appPublicKey' => self::APP_PUBLIC_KEY_DEFAULT
            );
            self::rsa($message, $param, $opType, $env);
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * 区操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数array(areaId=>区id,
     * appId=>游戏代码,
     * name=>区名,
     * status=>区审批状态,
     * regularId=>申请正式区为2，测试为1,
     * createUser=>申请创建人,)
     * @param string $opType 操作
     * @param string $env  环境
     * 
     * @return boolean 
     */
    public static function area (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType]) || ! isset($params['appId']) || ! isset($params['areaId'])) {
            $message = "Invalid Parameter";
            return false;
        }
        if ($opType != 'delete') {
            $need = array(
                'name', 
                'status', 
                //'regularId', 
                'createUser'
            );
            if(!isset($params['regularId'])) {
                $params['regularId'] = $env;    
            }
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
            
            //$params['atuhInfo'] = self::AUTH_INFO_DEFAULT;
        } else {
            $need = array(
                'status', 
                'regularId'
            );
            self::setDefault($params, $need);
        }
        $params['operate'] = self::$OPTypeList[$opType];
        $result = self::soapRequest('operateArea', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * 组操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数array(groupId=>游戏组标识，主键,
     * groupName=>游戏组名,
     * areaId=>游戏区标识，主键,
     * appId=>游戏ID,
     * createUser=>创建用户,
     * status=>"该游戏组目前的状态,1：有效,2：无效")
     * @param string $opType 操作类型
     * @param string $env  环境
     *
     * @return boolean 
     */
    public static function group (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType])) {
            $message = "Invalid Parameter";
            return false;
        }
        $need = array(
            'groupId', 
            'areaId', 
            'appId'
        );
        if (! self::_validateParam($params, $need, $message)) {
            return false;
        }
        //if ($opType != "delete") {
        if (! isset($params['status'])) {
            $params['status'] = self::GROUP_STATUS_DEFAULT;
        }
        //}
        $params['operate'] = self::$OPTypeList[$opType];
        $result = self::soapRequest('operateGroup', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * 公司操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数 array(spId=>SP编码,
     * spName=>公司名称,
     * spAddr=>公司地址,
     * email=>公司邮箱,
     * phoneNumber=>公司电话,
     * status=>效状态，默认0 （新申请无效），1表示有效 2表示更新变成无效,
     * beginTime=>开始时间date(Y-m-d H:i:s)必须格式,
     * endTime=>结束时间date(Y-m-d H:i:s)必须格式,
     * createUserId=>创建用户ID,
     * updateUserId=>更新用户ID,
     * companyUrl=>公司网址,
     * spCardNum=>身份证号,
     * productInfo=>公司产品简介,
     * notes=>备注,
     * zipCode=>邮编)
     * @param string $opType 操作类型
     * @param string $env  环境
     *
     * @return boolean 
     */
    public static function sp (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType]) || ! isset($params['spId'])) {
            $message = "Invalid Parameter";
            return false;
        }
        if ($opType != "delete") {
            if ($opType == 'add' && ! isset($params['updateUserId'])) {
                $params['updateUserId'] = 0;
            }
            $need = array(
                'spName', 
                'spAddr', 
                'email', 
                'phoneNumber', 
                'status', 
                'beginTime', 
                'endTime', 
                'createUserId', 
                'updateUserId', 
                'companyUrl', 
                'spCardNum', 
                'productInfo', 
                'notes', 
                'zipCode'
            );
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
            $need = array(
                'email', 
                'phoneNumber', 
                'companyUrl', 
                'productInfo', 
                'notes', 
                'spAddr', 
                'zipCode', 
                'spCardNum'
            );
            self::setDefault($params, $need, "N/A");
        } else {
            $params['status'] = 0;
        }
        $params['operate'] = self::$OPTypeList[$opType];
        //        print_r($params);
        //        echo $env;
        $result = self::soapRequest(
        'operateSp', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * IP操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数 array(groupId=>游戏组标识，主键,
     * areaId=>游戏区标识，主键,
     * appId=>游戏ID,
     * clientIp=>客户端IP,
     * clientProtNum=>客户端端口号,
     * clientType=>客户端类型,
     * status=>状态 1有效  2无效,
     * hostId=>1 电信 2 网通,
     * alias=>别名
     * )
     * @param string $opType 操作类型
     * @param string $env  环境
     *
     * @return mixed 
     */
    public static function ip (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType])) {
            $message = "Invalid Parameter";
            return false;
        }
        $need = array(
            'groupId', 
            'areaId', 
            'appId', 
            'clientIp', 
            'alias'
        );
        if ($opType!='select' && ! self::_validateParam($params, $need, $message)) {
            return false;
        }
        if ($opType != 'delete' && $opType!='select') {
            if (! isset($params['status'])) {
                $params['status'] = self::GROUP_STATUS_DEFAULT;
            }
            if (! isset($params['clientProtNum'])) {
                $params['clientProtNum'] = self::CLIENT_PORT_DEFAULT;
            }
            $need = array(
                'clientType', 
                'hostId'
            );
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
        } else {
            $need = array(
                'clientProtNum', 
                'clientType', 
                'status', 
                'hostId'
            );
            self::setDefault($params, $need);
        }
        $params['operate'] = self::$OPTypeList[$opType];
        $result = self::soapRequest('operateIp', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            if ($result->return->result == - 10236029) {
                $params['operate'] = 4;
                $selectResult = self::soapRequest('operateIp', $params, $message, $env);
                if ($selectResult && $selectResult->return->appId != $params['appId']) {
                	$message = 'ip+alias is used by oother app';
                    return false;
                }
            	return $result->return->ipId;
            }
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        if ($opType=='select') {
        	return (array)$result->return;
        }
        
        return $result->return->ipId;
    }
    /**
     * 公钥操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数array(spId=>公司ID,appId=>产品ID,appPublicKey=>产品公钥)
     * @param string $opType 操作类型
     * @param string $env  环境
     *
     * @return mixed 
     */
    public static function rsa (&$message, $params, $opType = 'add', $env = 1)
    {
        if (! isset(self::$OPTypeList[$opType])) {
            $message = "Invalid Parameter";
            return false;
        }
        $need = array(
            'appId', 
            'spId'
        );
        if (! self::_validateParam($params, $need, $message)) {
            return false;
        }
        $params['operate'] = self::$OPTypeList[$opType];
        $result = self::soapRequest('operateRsaKey', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        if ($opType == "select") {
            return $result->return->sndaPublicKey;
        }
        return $result->return->result == 0;
    }
    /**
     * 获取圈圈版本号
     * @param mixed $message 错误信息
     * @param array $ipList 二维数组 array(
     * array('127.0.0.1', 'kakka'),
     * array('192.0.0.1', 'lalla'),,,
     * )
     * @param int $env 环境
     * 
     * @return mixed 二维数组 array(array())
     */
    public static function getSdkVersion (&$message, $ipList, $env = 1)
    {
        if (! $ipList || ! is_array($ipList)) {
            $message = "Invalid Parameter";
            return false;
        }
        $ipAlias = "";
        $innerGlue = ",";
        $outerGlue = "#";
        foreach ($ipList as $row) {
            $ipAlias .= join($innerGlue, $row) . $outerGlue;
        }
        //长度限制
        if (isset($ipAlias[1001])) {
            $message = array(
                "code" => - 1, 
                "msg" => "the length of iplist too long"
            );
            return false;
        }
        $ipAlias = substr($ipAlias, 0, - 1);
        $opType = "select";
        $params = array(
            'ipAlias' => $ipAlias, 
            'operate' => self::$OPTypeList[$opType]
        );
        $result = self::soapRequest('operateSdkVersion', $params, $message, $env);
        if (!$result) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->return->result != 0) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message = isset(self::$errCodeMsg[$result->return->result]) ? self::$errCodeMsg[$result->return->result] : $result->return->result;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($params)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        $arr = array();
        if ($result->return->sdkVersion) {
            $tmp = explode($outerGlue, $result->return->sdkVersion);
            foreach ($tmp as $str) {
                $row = explode($innerGlue, $str);
                if ($row['2'] != - 10236048) {
                	$arr[] = $row;
                }
                
            }
            unset($tmp);
        }
        return $arr;
    }
    /**
     * 查询ip+alias是否存在
     * @param string $message 错误信息
     * @param string $ip
     * @param string $alias 别名 
     * @param int $env 环境
     * 
     * @return boolean
     */
    public static function existsIpAlias(&$message, $ip, $alias, $env = 1)
    {
        $arr = array(array($ip, $alias));
        if(self::getSdkVersion($message, $arr, $env)){
            return true;
        }
        return false;
    } 
    /**
     * 发送soap请求
     * 
     * @param string $apiName 方法名称
     * @param array $apiParam 参数
     * @param mixed $message 错误信息
     * @param $env 环境  1为联调，其它正式
     * @return mixed 
     */
    protected static function soapRequest ($apiName, $apiParam, &$message, $env = 1)
    {
        $wsdl = $env == 1 ? sdk_fetch_config(SDK_ENV . self::PRE_OAS_WSDL) : sdk_fetch_config(
        SDK_ENV . self::OAS_WSDL);
        $soap = self::getSoapInc($wsdl, array(
            'soap_version' => self::SOAP_VERSION
        ), $message);
        if (!$soap) {
        	return false;
        }
        //$apiParam = self::iconvArr($apiParam);
        //print_r($apiParam);
        $apiParam = array(
            self::REQUEST_FIELD => $apiParam
        );
        $result = $soap->$apiName($apiParam);
        //print_r($result);
        return $result;
    }
    /**
     * 设置数组参数默认值
     * @param array $arr 数组
     * @param array $need 需要填写默认值的变量
     * @param mixed $default 默认值
     * 
     * @return void
     */
    private static function setDefault (&$arr, $need, $default = 0)
    {
        foreach ($need as $k) {
            if(!isset($arr[$k]) || $arr[$k]===""){
                $arr[$k] = $default;    
            }
  
        }
    }
	/**
     * 自检函数
     */
    public static function selfTest() 
    {
    	$arr = array(
        	sdk_fetch_config(SDK_ENV . self::OAS_WSDL),
        	sdk_fetch_config(SDK_ENV . self::PRE_OAS_WSDL)
    	);
    	return self::curlTest($arr, array("oasServiceHttpSoap11Endpoint/"=>"wsdl"));
    }
} 
